package com.lecyon.farm.aspect;

import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.lecyon.farm.base.BaseRestRequest;
import com.lecyon.farm.base.BaseVo;
import com.lecyon.farm.comment.JwtUtil;
import com.lecyon.farm.common.annotation.ParamsCheck;
import com.lecyon.farm.common.constant.AuthorityConstant;
import com.lecyon.farm.common.validate.BeanValidateUtil;
import com.lecyon.farm.util.RedisUtils;
import com.lecyon.farm.util.StringHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author Yao Zheng
 * @Description: service 层入参校验切点
 * @Date 2019/7/30 15:23
 */
@Aspect
@Component
public class ServiceValidateAspect {

    private RedisUtils redisUtils;


    @Autowired
    public ServiceValidateAspect(RedisUtils redisUtils) {
        this.redisUtils = redisUtils;
    }

    /**
     * service 层切点
     */
    @Pointcut("execution(* com.lecyon.farm.service.impl.*.*(..))")
    public void servicePointcut() {
    }

    /**
     * service 层入参校验
     *
     * @param joinPoint 切点
     * @return
     * @throws Throwable
     */
    @Around(value = "servicePointcut()")
    public Object serviceParamCheckAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 判断是否需要校验
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        ParamsCheck paramsCheckAnnotation = method.getAnnotation(ParamsCheck.class);
        if (paramsCheckAnnotation != null && paramsCheckAnnotation.ignore()) {
            return joinPoint.proceed();
        }
        /**
         * 参数校验
         */
        Object[] objects = joinPoint.getArgs();
        String userToken;
        BaseVo tempBaseVo;
        BaseRestRequest tempBaseRequest;
        boolean flag;
        for (Object arg : objects) {
            if (arg == null) {
                break;
            }
            boolean isChildClass = Model.class.isAssignableFrom(arg.getClass());
            if (isChildClass) {
                // 参数校验
                String validResult = BeanValidateUtil.validate(arg);
                if (validResult != null && validResult.length() > 0) {
                    break;
//                    throw new ParamsCheckException(validResult);
                }
            }
            // 判断是否为HardwareRequestVo的子类
            isChildClass = arg instanceof String;
            if (isChildClass) {
                //如果是，跳过token认证
                continue;
            }
            // 判断是否为BaseVo的子类
            isChildClass = arg instanceof BaseVo;
            if (isChildClass) {
                // 权限校验
                tempBaseVo = (BaseVo) arg;
                userToken = tempBaseVo.getUserToken();
                if (StringHelper.isEmpty(userToken)) {
                    tempBaseVo.setUserToken(AuthorityConstant.DEFAULT_SYS_TOKEN);
                    userToken = tempBaseVo.getUserToken();
                }
                flag = redisUtils.hasKey(userToken);
                if (!flag) {
                    break;
                }
                String sysUserId = JwtUtil.getSysUserId(userToken);
                flag = redisUtils.hasKey(sysUserId);
                if (!flag) {
                    break;
                }
            }
            isChildClass = arg instanceof BaseRestRequest;
//            if (isChildClass) {
//                // 权限校验
//                tempBaseRequest = (BaseRestRequest) arg;
//                userToken = tempBaseRequest.getUserToken();
//                if (StringHelper.isEmpty(userToken)) {
//                    throw new ParamsCheckException(CommonConstant.EX_AUTHORITY_ERROR_MSG);
//                }
//                flag = redisUtils.hasKey(userToken);
//                if (!flag) {
//                    break;
//                }
//                String sysUserId = JwtUtil.getSysUserId(userToken);
//                flag = redisUtils.hasKey(sysUserId);
//                if (!flag) {
//                    break;
//                }
//            }
        }

        return joinPoint.proceed();
    }
}
